import { S as SwitchSetting } from "./switchHelpers.js";
import { C as ClassifierSetting } from "./classifierHelpers.js";

// Enums for Node Types
const NodeType = {
  ID: "ID",
  WHEN: "WHEN",
  THEN: "THEN",
  SWITCH: "SWITCH",
  IF: "IF",
  GROUP: "GROUP",
  BREAK: "BREAK",
  OR: "OR",
  AND: "AND",
  NOT: "NOT",
};

// Enums for Group Types
const GroupType = {
  CATCH: "CATCH",
  LOGIC: "LOGIC",
  CONFIG: "CONFIG",
  FOR: "FOR",
  WHILE: "WHILE",
  ITERATOR: "ITERATOR",
};

// Helper: Shallow copy with symbol support
function shallowCopyWithSymbols(target, source) {
  for (const key in source) {
    if (Object.prototype.hasOwnProperty.call(source, key)) {
      target[key] = source[key];
    }
  }
  if (Object.getOwnPropertySymbols) {
    for (const sym of Object.getOwnPropertySymbols(source)) {
      if (Object.prototype.propertyIsEnumerable.call(source, sym)) {
        target[sym] = source[sym];
      }
    }
  }
  return target;
}

/**
 * Node for logic flow
 */
export class Node {
  constructor(id = "") {
    this.originType = "";
    this.anchorsNextIds = [];
    this.id = id;
    this.child = [];
    this.maxLineNum = 25;
  }
  addChild(node) {
    if (!this.child) this.child = [];
    this.child.push(node);
  }
  get childFirstId() {
    if (!Array.isArray(this.child) || this.child.length === 0) return "";
    const first = this.child[0];
    switch (first.type) {
      case NodeType.WHEN:
      case NodeType.THEN:
        return first.childFirstId;
      default:
        return first.id;
    }
  }
  // 获取节点的EL表达式 (带tag和data)
  getElString() {
    const tagStr = this.properties?.tag ? `.tag('${this.properties.tag}')` : "";
    const dataStr = this.properties?.data ? `.data('${this.properties.data}')` : "";
    return `${this.getElStringRaw()}${tagStr}${dataStr}`;
  }
  // 获取节点的基础EL表达式
  getElStringRaw() {
    if (this.type === NodeType.ID) return this.nodeId;
    if (this.elString) return this.elString;

    console.log("nodeType"+this.type);
    switch (this.type) {
      case NodeType.IF: return this.getELString_IF();
      case NodeType.GROUP: return this.getELString_Group();
      case NodeType.SWITCH: return this.getELString_SWITCH();
      case NodeType.WHEN:
      case NodeType.THEN: return this.getElString_WHEN_THEN();
      case "code": return this.id;
      default: return this.type;
    }
  }
  // 为每一行插入空格用于格式化
  insertSpace(str) {
    return "    " + str.split("\n").join("\n    ");
  }
  // 处理WHEN/THEN节点
  getElString_WHEN_THEN() {
    const children = this.child || [];
    let aliasStr = "", firstIdStr = "";
    if (this.aliasId) {
      aliasStr = this.aliasId.startsWith("tag:") ? `.tag("${this.aliasId.substring(4)}")` : `.id("${this.aliasId}")`;
    }
    if (this.childFirstId) {
      firstIdStr = `.tag("${this.childFirstId}")`;
    }
    const childStrings = children.map(c => c.getElString());
    const joined = childStrings.join(",");
    if (children.length === 1 && (!this.aliasId || [NodeType.THEN, NodeType.WHEN].includes(children[0].type))) {
      return `${joined}${aliasStr}`;
    }
    if (joined.length < this.maxLineNum - 6) {
      return `${this.type}(${joined})${firstIdStr || aliasStr}`;
    }
    return `${this.type}(\n${this.insertSpace(childStrings.join(",\n"))}\n)${firstIdStr || aliasStr}`;
  }
  // 分组节点解析
  getELString_Group() {
    const children = this.child || [];
    const childStr = children.map(w => w.getElString()).join(",");
    if (this.groupType === GroupType.CONFIG) {
      const ignoreErr = this.properties?.ignoreError ? ".ignoreError(true)" : "";
      const any = this.properties?.any ? "any(true)" : "";
      const must = this.properties?.must ? `must(${this.properties.must})` : "";
      return `${childStr}${ignoreErr}${any}${must}`;
    }
    if (this.groupType === GroupType.LOGIC) {
      return this.elString;
    }
    if (this.groupType === GroupType.CATCH) {
      const exNodeStr = this.exceptionNode.getElString();
      return `${this.groupType}(${childStr}).DO(${exNodeStr})`;
    }
    const breakStr = this.breakNode ? `.BREAK(${this.breakNode.getElString()})` : "";
    const startStr = this.startNode?.nodeId ? this.startNode.getElString() : this.startNum;
    if (children.length === 1) {
      return `${this.groupType}(${startStr}).DO(${childStr})${breakStr}`;
    }
    return `${this.groupType}(${startStr}).DO(WHEN(${childStr}))${breakStr}`;
  }
  getELString_IF() {
    const childStrings = (this.child || []).map(s => s.getElString());
    const joined = childStrings.join(",");
    if (joined.length < this.maxLineNum - 4) {
      return `IF(${joined})`;
    }
    return `IF(\n${this.insertSpace(childStrings.join(",\n"))}\n)`;
  }
  getELString_SWITCH() {
    
    this.parseSwitchChildren();
    const childStrings = (this.child || []).map(a => a.getElString());
    const joined = childStrings.join(",");
    const baseType = this.originType || NodeType.SWITCH;
    const tagStr = `${baseType}.tag('${this.nodeId}')`;
    const idTagStr = `.tag('${this.id}')`;
    if (joined.length < this.maxLineNum - 13 - this.nodeId.length) {
      return `SWITCH(${tagStr}).to(${joined})${idTagStr}`;
    }
    return `SWITCH(${tagStr}).to(\n${this.insertSpace(childStrings.join(",\n"))}\n)${idTagStr}`;
  }
  // 处理SWITCH子节点
  parseSwitchChildren() {
    if (!this.anchorsNextIds.length) return;
    const children = this.child || [];
    if (children.length <= this.anchorsNextIds.length) return;
    for (const { nextIds } of this.anchorsNextIds) {
      if (nextIds.length <= 1) continue;
      const whenNode = new Node();
      whenNode.type = NodeType.WHEN;
      for (let i = 0; i < nextIds.length; i++) {
        const targetId = nextIds[i];
        const idx = children.findIndex(p => {
          let id = p.id;
          if (!id && p.child.length > 0) id = p.child[0].id;
          return id === targetId || p.childFirstId === targetId;
        });
        if (idx !== -1) {
          if (i === 0) {
            whenNode.addChild(children.splice(idx, 1, whenNode)[0]);
          } else {
            whenNode.addChild(children.splice(idx, 1)[0]);
          }
        }
      }
    }
    this.child = children;
  }
}

// 简单栈管理器
export class Stack {
  constructor() {
    this.stack = [];
    this.ebpStack = [];
  }
  peek(arr) { return arr[arr.length - 1]; }
  pop() { return this.stack.pop(); }
  push(item) { this.stack.push(item); }
  clear() { this.stack = []; }
  resolve() {
    const ebp = this.peek(this.ebpStack);
    const start = this.stack[ebp + 1];
    for (let i = ebp + 2; i < this.stack.length; i++) {
      start.addChild(this.stack[i]);
    }
    return start;
  }
  quit() {
    const resolved = this.resolve();
    const base = this.stack[this.peek(this.ebpStack)];
    while (this.stack.length > this.peek(this.ebpStack)) this.stack.pop();
    this.stack.push(resolved);
    this.ebpStack.pop();
    return base;
  }
  create() {
    this.ebpStack.push(this.stack.length);
    this.stack.push(new Node());
  }
  addEndPoint(node) { this.stack[this.peek(this.ebpStack)] = node; }
  getEndPoint() { return this.stack[this.peek(this.ebpStack)]; }
}

// 逻辑转换核心
export class LogicContext {
  constructor(anchorNextIdsMap) {
    this.endPoints = {};
    this.sourceNum = {};
    this.nodeMap = {};
    this.inGrooupNode = {};
    this.elStack = new Stack();
    this.startId = "start";
    this.endId = "end";
    this.anchorNextIdsMap = anchorNextIdsMap;
  }
  isEnd(id) { return this.endId === id; }
  isStart(id) { return this.startId === id; }
  getNodeById(id) { return this.nodeMap[id]; }
  // 建立边
  initEdge(src, tgt, text = "") {
    if (this.inGrooupNode[src] || this.inGrooupNode[tgt]) return;
    this.endPoints[src] = this.endPoints[src] || [];
    const targetNode = this.nodeMap[tgt];
    targetNode.comingEdgeText = text;
    this.endPoints[src].push(targetNode);
    this.sourceNum[tgt] = (this.sourceNum[tgt] || 0) + 1;
  }
  // 初始化所有节点和边
  init(logicFlow) {
    const groupNodes = [];
    logicFlow.nodes.forEach(node => {
      if (!node.id) return;
      if (node.type === NodeType.GROUP) {
        groupNodes.push(node);
      } else {
        this.initELNode(node);
      }
    });
    groupNodes.forEach(node => this.initLoopELNode(node));
    // add start/end nodes
    const startNode = new Node(this.startId);
    this.nodeMap[this.startId] = startNode;
    const endNode = new Node(this.endId);
    this.nodeMap[this.endId] = endNode;
    // add edges
    logicFlow.edges.forEach(edge => {
      const { sourceNodeId: src, targetNodeId: tgt, text } = edge;
      if (!src || !tgt) return;
      if (this.nodeMap[src].type === NodeType.IF)
        this.parseIFEdge(text?.value, src, tgt);
      else
        this.initEdge(src, tgt, text?.value);
    });
    // ensure all nodes have start/end
    logicFlow.nodes.forEach(node => {
      if (!node.id || this.inGrooupNode[node.id]) return;
      if (!this.endPoints[node.id]) this.initEdge(node.id, this.endId);
      if (!this.sourceNum[node.id]) this.initEdge(this.startId, node.id);
    });
    if (logicFlow.nodes.length === 0) this.initEdge(this.startId, this.endId);
  }
  // 处理IF节点分支
  parseIFEdge(text, src, tgt) {
    const tgtNode = this.nodeMap[tgt];
    let arr = this.endPoints[src] || [undefined, undefined];
    if (this.isTrueText(text)) {
      if (arr[0]) arr[1] = arr[0];
      arr[0] = tgtNode;
    } else if (this.isFalseText(text)) {
      if (arr[1]) arr[0] = arr[1];
      arr[1] = tgtNode;
    } else {
      arr[0] ? arr[1] = tgtNode : arr[0] = tgtNode;
    }
    this.endPoints[src] = arr;
    this.sourceNum[tgt] = (this.sourceNum[tgt] || 0) + 1;
  }
  isTrueText(text) {
    return ["是", "true", "True", "TRUE"].includes(text);
  }
  isFalseText(text) {
    return ["否", "false", "False", "FALSE"].includes(text);
  }
  // 将logicFlow节点转为Node
  initELNode(node) {
    node.properties = shallowCopyWithSymbols({}, node.properties || {});
    node.properties.nodeId = node.id;
    node.properties.name = node.properties.text;
    node.properties.tag = node.id;
    const elNode = new Node();
    elNode.id = node.id;
    elNode.type = this.typeFormat(node.type);
    elNode.originType = node.type;
    this.handleSwitchNode(elNode, node);
    elNode.properties = node.properties;
    elNode.nodeId = node.properties.nodeId;
    elNode.name = node.properties.name;
    elNode.groupType = node.properties.groupType;
    elNode.data = node.properties.data;
    elNode.aliasId = node.properties.aliasId;
    elNode.tag = node.properties.tag;
    elNode.startNum = node.properties.startNum;
    this.nodeMap[elNode.id] = elNode;
    return elNode;
  }
  handleSwitchNode(node, rawNode) {

    if (node.type !== NodeType.SWITCH) return;
    const setting = node.originType === "switch" ? SwitchSetting : ClassifierSetting;
    const caseList = setting.getCaseList(rawNode);
    for (let i = 0; i < caseList.length; i++) {
      const c = caseList[i];
      const anchorId = setting.getAnchorId(rawNode.id, c.type, i + 1);
      const anchorNextIds = this.anchorNextIdsMap.get(anchorId);
      if (anchorNextIds && anchorNextIds.length > 0) {
        node.anchorsNextIds.push({ anchorId, nextIds: anchorNextIds });
      }
    }
  }
  // 处理Group节点
  initLoopELNode(node) {
    const elNode = this.initELNode(node);
    if (elNode.groupType === GroupType.LOGIC) {
      elNode.elString = this.getLogicStr(node.flowData);
    } else {
      // @ts-ignore
      elNode.addChild(new Parser(node.flowData).parse());
    }
    this.nodeMap[elNode.id] = elNode;
    node.flowData.nodes.forEach(subNode => {
      this.inGrooupNode[subNode.id] = true;
    });
    node.sourceNodeIds?.forEach(src => this.initEdge(src, elNode.id));
    node.targetNodeIds?.forEach(tgt => this.initEdge(elNode.id, tgt));
  }
  typeFormat(type) {
    if (type === "switch" || type === "classifier") return NodeType.SWITCH;
    if (type === "IF") return NodeType.IF;
    if (type === "SWITCH") return NodeType.SWITCH;
    if (type === "GROUP") return NodeType.GROUP;
    if (type === "AND") return NodeType.AND;
    if (type === "NOT") return NodeType.NOT;
    if (type === "OR") return NodeType.OR;
    return type;
  }
  setSourceNum(node, n) { this.sourceNum[node.id] = n; }
  getSourceNum(node) { return this.sourceNum[node.id] || 0; }
  getEndNum(node) { const arr = this.endPoints[node.id]; return arr ? arr.length : 0; }
  getEndList(node) { return this.endPoints[node.id] || []; }
  push(node) { this.elStack.push(node); }
  pop() { return this.elStack.pop(); }
  createStackEnv(node) {
    this.elStack.create();
    const n = new Node();
    n.id = node.id;
    n.type = node.type;
    n.originType = node.originType;
    n.groupType = node.groupType;
    n.aliasId = node.aliasId;
    n.name = node.name;
    n.data = node.data;
    n.tag = node.tag;
    n.nodeId = node.nodeId;
    n.child = node.child;
    n.comingEdgeText = node.comingEdgeText;
    n.elString = node.elString;
    n.anchorsNextIds = node.anchorsNextIds;
    n.startNode = node.startNode;
    n.breakNode = node.breakNode;
    n.exceptionNode = node.exceptionNode;
    n.startNum = node.startNum;
    this.elStack.push(n);
  }
  quitStackEnv() { return this.elStack.quit(); }
  setStackEndPoint(node) { this.elStack.addEndPoint(node); }
  // 逻辑Group转字符串
  getLogicStr(logicFlow) {
    const nodeMap = {};
    logicFlow.nodes.forEach(n => nodeMap[n.id] = n);
    const incomingCount = {};
    logicFlow.edges.forEach(e => {
      incomingCount[e.sourceNodeId] = (incomingCount[e.sourceNodeId] || 0) + 1;
    });
    const startId = logicFlow.nodes.map(x => x.id).find(id => !incomingCount[id]);
    function dfs(id) {
      const n = nodeMap[id];
      const preds = logicFlow.edges.filter(e => e.targetNodeId === id).map(e => e.sourceNodeId);
      const predStrs = preds.map(pid => {
        const pn = nodeMap[pid];
        if (pn.type === NodeType.ID) return pn.properties?.nodeId;
        if ([NodeType.AND, NodeType.OR, NodeType.NOT].includes(pn.type)) return dfs(pn.id);
        throw new Error("Unknown node type");
      }).join(",");
      return `${n.type}(${predStrs})`;
    }
    return dfs(startId);
  }
}

// 主解析器
export class Parser {
  constructor(logicFlow, anchorNextIdsMap) {
    this.logicFlow = logicFlow;
    this.context = new LogicContext(anchorNextIdsMap);
    this.context.init(this.logicFlow);
  }
  parse() {
    const startId = this.context.startId;
    const startNode = new Node(startId);
    this.parseThenChain(startNode);
    return this.context.pop();
  }
  parseThenChain(node, targetNode, defaultData, aliasId = "") {
    this.context.createStackEnv({ type: NodeType.THEN, aliasId });
    if (defaultData) this.context.push(defaultData);
    this.parseSingleNode(node, { targetNode });
    this.context.quitStackEnv();
  }
  parseSingleNode(node, opts) {
    const id = node.id;
    const endNum = this.context.getEndNum(node);
    const { targetNode } = opts;
    if (this.context.isEnd(id)) {
      this.context.setStackEndPoint(node);
      return null;
    }
    if (targetNode && targetNode.id === node.id) {
      this.context.setStackEndPoint(node);
      return null;
    }
    if (this.context.isStart(id) || this.context.push(node), node.type === NodeType.IF) {
      const nf = this.parseIF(this.context.pop());
      return this.parseSingleNode(nf, { targetNode });
    }
    if (node.type === NodeType.SWITCH) {
      const nf = this.parseWhich(this.context.pop());
      return this.parseSingleNode(nf, { targetNode });
    }
    if (node.type === NodeType.GROUP) {
      let nf = this.parseGroup(this.context.pop());
      if (node.groupType === GroupType.LOGIC && endNum > 0 && !this.context.isEnd(this.context.getEndList(node)[0].id)) {
        const next = this.context.pop();
        nf = this.parseIF(next);
      }
      return this.parseSingleNode(nf, { targetNode });
    }
    if (endNum === 1) {
      return this.parseSingleNode(this.context.getEndList(node)[0], { targetNode });
    }
    const w = this.parseWhenChain(node);
    return this.parseSingleNode(w, { targetNode });
  }
  parseBranch(node) {
    const ends = this.context.getEndList(node);
    let branchEnd = this.getBranchEnd(node);
    ends.forEach(nextNode => {
      if (nextNode.id !== branchEnd.id) {
        this.parseThenChain(nextNode, branchEnd, undefined, node.type === NodeType.SWITCH ? nextNode.comingEdgeText : "");
      }
    });
    return branchEnd;
  }
  parseIF(node) {
    const n = new Node();
    n.type = NodeType.IF;
    this.context.createStackEnv(n);
    if (node.type === NodeType.IF) node.type = NodeType.ID;
    this.context.push(node);
    const outs = this.context.getEndList(node).filter(Boolean);
    if (outs.length === 1) {
      let c, p;
      try {
        c = outs[0];
        p = this.context.endPoints[c.id][0];
        if (!this.context.isEnd(p.id)) throw new Error();
      } catch {
        throw new Error("IF 判断节点的分支数必须为2");
      }
      this.context.push(c);
      return p;
    }
    if (outs.length !== 2) throw new Error("IF 判断节点的分支数必须为2");
    const branchEnd = this.parseBranch(node);
    this.context.setStackEndPoint(branchEnd);
    return this.context.quitStackEnv();
  }
  // SWITCH节点多分支
  parseWhich(node) {
    if (this.context.getEndList(node).length <= 1) throw new Error("WHICH 分支节点的分支数必须大于1");
    this.context.createStackEnv(node);
    const branchEnd = this.parseBranch(node);
    this.context.setStackEndPoint(branchEnd);
    return this.context.quitStackEnv();
  }
  parseWhenBase(follows, end, datas) {
    this.context.createStackEnv({ type: NodeType.WHEN });
    follows.forEach((n, i) => {
      if (n.id !== end.id) {
        this.parseThenChain(n, end, datas[i]);
      }
    });
    this.context.quitStackEnv();
    return this.context.pop();
  }
  parseWhenChain(node) {
    this.context.createStackEnv({ type: NodeType.WHEN });
    const ends = this.context.getEndList(node);
    const branchEnd = this.getBranchEnd(node);
    const branchMap = this.getBranchEnd(node, branchEnd);
    const result = {};
    const group = {};
    Object.entries(branchMap).sort(([, a], [, b]) => a.length - b.length).forEach(([id, indices]) => {
      const n = this.context.getNodeById(id);
      if (indices.length === 1) return;
      const arr = [];
      indices.forEach(idx => {
        const e = ends[idx];
        arr.push(result[e.id] || e.id);
      });
      indices.forEach(idx => {
        const e = ends[idx];
        result[e.id] = id;
      });
      const nodes = Array.from(new Set(arr)).map(x => this.context.getNodeById(x));
      const w = this.parseWhenBase(nodes, n, nodes.map(x => group[x.id]));
      group[id] = w;
    });
    this.context.push(group[branchEnd.id]);
    this.context.setStackEndPoint(branchEnd);
    return this.context.quitStackEnv();
  }
  parseGroup(node) {
    const ends = this.context.getEndList(node);
    let last, allSpecial = true;
    ends.forEach(n => {
      if (n.comingEdgeText) {
        this.parseThenChain(n);
        const child = this.context.elStack.pop();
        switch (n.comingEdgeText) {
          case "START": node.startNode = child.child[0]; break;
          case "BREAK": node.breakNode = child.child[0]; break;
          case "EXCEPTION": node.exceptionNode = child.child[0]; break;
        }
      } else {
        last = n;
        allSpecial = false;
      }
    });
    this.context.elStack.push(node);
    return allSpecial ? new Node(this.context.endId) : last;
  }
  // 获取分支的结束节点
  getBranchEnd(node, endNode) {
    const map = {};
    let endNum = this.context.getEndNum(node);
    const endIds = this.context.getEndList(node).map(n => n.id);
    const count = {};
    for (;;) {
      for (let i = 0; i < endIds.length; i++) {
        const id = endIds[i];
        if (!id) continue;
        const n = this.context.getNodeById(id);
        count[n.id] = (count[n.id] || 0) + 1;
        map[n.id] = map[n.id] || [];
        map[n.id].push(i);
        if (count[n.id] === endNum) {
          if (node.type === NodeType.SWITCH && this.context.getEndList(node).some(x => x.id === n.id)) {
            return this.getBranchEnd(n);
          }
          return endNode ? map : n;
        }
        if (this.context.isEnd(n.id) || n.id === endNode?.id) {
          endIds[i] = "";
        } else if (this.context.getEndNum(n) > 1) {
          endIds[i] = this.getBranchEnd(n).id;
        } else {
          endIds[i] = this.context.getEndList(n)[0].id;
        }
      }
    }
  }
}
